package quest.trigger
{
import core.log.GameLogType;
import core.model.GameModel;
import core.model.QuestModel;

import flash.utils.Dictionary;
import flash.utils.getDefinitionByName;

import quest.QuestManager;

import values.quest.QuestGroupTemplateValue;
import values.quest.QuestSettingValue;
import values.quest.QuestTemplateValue;
import values.quest.QuestTemplateValueList;
import values.quest.QuestValue;

/**
 *  QuestTrigger
 * @author jliang
 * 
 */
public class QuestTrigger
{
	private var handlers:Dictionary = new Dictionary(true); /* IQuestTriggerHandler */
	private var logMap:Dictionary = new Dictionary(true); /* Dictionary */
	
	private var triggerableGroups:Dictionary = new Dictionary(true);   /* QuestGroupTemplateValue */
	
	private var model:QuestModel;
	
	public function QuestTrigger()
	{
		model = GameModel.instance.questModel;
		
		for (var i:int = 0; i < QuestSettingValue.questTriggers.length(); i++)
		{
			var def:* = QuestSettingValue.questTriggers[i];
			var ref:String = def.@class_ref;
			var classRef:Class = getDefinitionByName("quest.handler." + ref) as Class;
			var handler:IQuestTriggerHandler = new classRef(QuestManager.instance);
			handlers[handler.key] = handler;
			
			//add handler from log map
			var logs:Array = String(def.@logs).split(",");
			for each (var log:String in logs)
			{
				var map:Dictionary = logMap[log];
				if (!map)
				{
					map = new Dictionary(true);
					logMap[log] = map;
				}
				map[handler.key] = handler;
			}
		}
	}
	
	public function check(type:String, ...args):void
	{
		var params:Array;
		var handler:IQuestTriggerHandler;
		if (type == GameLogType.LEVEL_UP || 
			type == GameLogType.QUEST_COMPLETE ||
			type == GameLogType.GAME_START)
		{
			firstCheckRestQuest();
			params = [ triggerableGroups, type ].concat(args);
			for each (handler in handlers)
			{
				handler.check.apply(handler, params);
			}
			return;
		}
		
		var map:Dictionary = logMap[type];
		if (!map) return;
		
		params = [ triggerableGroups, type ].concat(args);
		for each (handler in map)
		{
			handler.check.apply(handler, params);
		}
	}
	
	public function checkNextQuest(questValue:QuestValue):void
	{
		if (questValue.template.group.isLastQuest(questValue.template.key))
		{
			return;
		}
		
		var index:int = questValue.template.group.getQuestIndex(questValue.template.key);		
		var newQuest:QuestValue = createQuestValueByTemplate(questValue.template.group.getQuestByIndex(index + 1));
		
		QuestManager.instance.questAppear(newQuest);
	}
	
	private function hasHandler(key:String):Boolean
	{
		return handlers[key] != null;
	}
	
	private function firstCheckRestQuest():void
	{
		var level:int = GameModel.instance.playerModel.level.level;
		for each (var group:QuestGroupTemplateValue in QuestSettingValue.questGroups)
		{
			if (model.hasQuestGroupCompleted(group.key) || model.isQuestGroupExsit(group.key))
			{
				continue;
			}
			if (group.requiredLevel <= level)
			{
				var questRequiredMeet:Boolean = true;
				if (group.requiredGroups.length > 0)
				{
					for each (var groupKey:String in group.quests)
					{
						if (!model.hasQuestGroupCompleted(group.key))
						{
							questRequiredMeet = false;
							break;
						}
					}
				}
				if (questRequiredMeet)
				{
					//quest group meet level and quest requirement
					//group dosen't need other requirements.
					if (!group.needToBeTriggered)
					{						
						QuestManager.instance.questAppear(createQuestValueByTemplate(group.getQuestByIndex(0)));
					}
					else
					{
						triggerableGroups[group.key] = group;
					}
				}
			}
		}
	}
	
	private function createQuestValueByKey(key:String):QuestValue
	{
		return createQuestValueByTemplate(QuestTemplateValueList.getByKey(key));
	}
	
	private function createQuestValueByTemplate(template:QuestTemplateValue):QuestValue
	{
		var questValue:QuestValue = new QuestValue();
		questValue.template = template;
		return questValue;
	}
	
}
}


